package pers.yaoliguo.bms.control.activity;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import pers.yaoliguo.bms.control.view.Message;
import pers.yaoliguo.bms.uitl.MD5Util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.NativeModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.validation.ProcessValidator;
import org.activiti.validation.ProcessValidatorFactory;
import org.activiti.validation.ValidationError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
@RequestMapping(value = "/ModelControl")
public class modelHanlder implements ModelDataJsonConstants {
	protected static final Logger LOGGER = LoggerFactory.getLogger(modelHanlder.class);
	@Resource
	ProcessEngine engine;
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	ManagementService managementService;
	protected Logger logger = LoggerFactory.getLogger(getClass());

	@RequestMapping(value = { "/skipModelPage" }, method = {
			org.springframework.web.bind.annotation.RequestMethod.GET }, produces = { "application/json" })
	public String getEditorJson() {
		return "redirect:/views/activity/modelList.html";
	}
	
	@RequestMapping(value={"/skipDeployPage"},method = {
			org.springframework.web.bind.annotation.RequestMethod.GET })
  	public String skipDeployPage(){
  		
  		return "redirect:/views/activity/deployList.html";
  	}
	
	@RequestMapping("/updateModel")
	public String updateModel(String modelId){
		return "redirect:/views/activity/modeler.html?modelId="+modelId;
	}
	
	@ResponseBody
  	@RequestMapping(value="/deploy/getDeployList")
  	public Object getDeployList(){
		Message<Map> msg = new Message<Map>();
  		
  		try {
  			List<Deployment> deplist = engine.getRepositoryService()//
				  					.createDeploymentQuery()//
				  					.orderByDeploymenTime()//
				  					.asc()//
				  					.list();
  			List<Map> list = new ArrayList<Map>();
  			for (Deployment dep : deplist) {
  				Map<String, Object> map = new HashMap<String, Object>();
  				map.put("id",dep.getId());
  				map.put("name",dep.getName());
  				map.put("DeploymentTime",dep.getDeploymentTime());
  				list.add(map);
			}
  			msg.setDataList(list);
  			msg.setResult("200");
		} catch (Exception e) {
			msg.setResult("500");
			msg.setInfo(e.getMessage());
		}
  		
  		return msg;
  	}
	
	@ResponseBody
	@RequestMapping("/deleteDepolyProcess")
	public Object deleteDepolyProcess(HttpServletRequest req){
		String depId = req.getParameter("depId");
		Message msg = new Message();
		
		try {
			engine.getRepositoryService().deleteDeployment(depId);
			msg.setResult("200");
		} catch (Exception e) {
			msg.setResult("500");
			msg.setInfo(e.getMessage());
		}
		
		return msg;
	}
	
	@RequestMapping("/viewProcessImg")
	public void viewProcessImg(HttpServletRequest req, HttpServletResponse resp){
		String depId = req.getParameter("depId");
		
		ProcessDefinition Pdf =  engine.getRepositoryService()//
						.createNativeProcessDefinitionQuery()//
						.sql("SELECT * FROM "+managementService.getTableName((ProcessDefinition.class))+" WHERE DEPLOYMENT_ID_="+depId)//
						.singleResult();
		
		String imgName = Pdf.getDiagramResourceName();
		String processName =Pdf.getResourceName();
		
		InputStream in = engine.getRepositoryService().getResourceAsStream(depId, imgName);
		OutputStream out = null;
		byte [] buf = new byte[1024];
		int legth = 0;
		try {
			out = resp.getOutputStream();
			while ((legth = in.read(buf)) != 0) {
					out.write(buf,0,legth);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(in != null){
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(out != null){
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	@ResponseBody
	@RequestMapping("/deleteModel")
	public Object deleteModel(String modelId){
		Message<Model> msg = new Message<Model>();
		try {
			engine.getRepositoryService().deleteModel(modelId);
			msg.setResult("200");
		} catch (Exception e) {
			msg.setResult("500");
			msg.setInfo(e.getMessage());
			logger.error("删除model异常信息："+e.getMessage());
		}
		
		return msg;
	}
	
	@RequestMapping("/createModel")
	@ResponseBody
	public Object createModel(@RequestBody MultiValueMap<String, String> values, HttpServletRequest request, HttpServletResponse response) {
		String processName = null;
		int version = 1;
		Message message = new Message();
		try {
			processName = (String) values.getFirst("name");
			try {
				version = Integer.parseInt((String)values.getFirst("version"));
            } catch (Exception e) {
				// TODO: handle exception
            	version = 1;
			}
			RepositoryService repositoryService = engine.getRepositoryService();
			ObjectMapper objectMapper = new ObjectMapper();
			String uuid = UUID.randomUUID().toString();
			ObjectNode editorNode = objectMapper.createObjectNode();
			editorNode.put("id", uuid);
			editorNode.put("resourceId", uuid);
			ObjectNode stencilSetNode = objectMapper.createObjectNode();
			stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
			editorNode.put("stencilset", stencilSetNode);
			Model modelData = repositoryService.newModel();
			ObjectNode modelObjectNode = objectMapper.createObjectNode();
			modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processName);
			modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
			String description = "建立activity的model";
			modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
			modelData.setMetaInfo(modelObjectNode.toString());
			modelData.setName(processName);
			modelData.setKey(MD5Util.encrypt(processName));
			modelData.setVersion(version);
			// 保存模型
			repositoryService.saveModel(modelData);
			repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
			message.setResult("200");
		} catch (Exception e) {
			logger.error("创建模型失败：", e);
			message.setResult("500");
		}
		return message;
	}
	
	@ResponseBody
	@RequestMapping("/getModelList")
	public Object getModelList(){
		Message<Model> msg = new Message<Model>();
		List<Model> list =  new ArrayList<Model>();
		try {
			list =   engine//
					.getRepositoryService()//
					.createModelQuery()//
					.orderByCreateTime()//
					.asc()//
					.list();
			msg.setResult("200");
		} catch (Exception e) {
			msg.setResult("500");
			msg.setInfo(e.getMessage());
			logger.error("查询model列表异常信息："+e.getMessage());
		}
		
		msg.setDataList(list);
		
		return msg;
	}
	
	@ResponseBody
	@RequestMapping("/deployModel")
	public Object deployModel(String modelId){
		Message<Model> msg = new Message<Model>();
		try {
			Model modelData = engine.getRepositoryService().getModel(modelId);
			ObjectNode modelNode = (ObjectNode)new ObjectMapper()//
											.readTree(engine.getRepositoryService()//
											.getModelEditorSource(modelData.getId()));
			 byte[] bpmnBytes = null;
			 BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);
			 
			 //验证bpmnModel 是否是正确的bpmn xml文件
			 ProcessValidatorFactory processValidatorFactory=new ProcessValidatorFactory();
			 ProcessValidator defaultProcessValidator = processValidatorFactory.createDefaultProcessValidator();
			 //验证失败信息的封装ValidationError
			 List<ValidationError> validate = defaultProcessValidator.validate(bpmnModel);
			 if(validate.size() > 0){
				 logger.error(validate.toString());
			 }
			 bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
			 String processName = modelData.getName() + ".bpmn20.xml";
			 Deployment dep = engine.getRepositoryService()//
					 				.createDeployment()//
					 				.name(modelData.getName())//
					 				.addString(processName, new String(bpmnBytes,"UTF-8"))//
					 				.deploy();
			msg.setResult("200");
		} catch (Exception e) {
			msg.setResult("500");
			msg.setInfo(e.getMessage());
			e.printStackTrace();
			logger.error("部署model异常信息："+e.getMessage());
		}
		
		return msg;
		
	}
	
	
}
